<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>根据不同用户拥有的菜单权限来动态地显示菜单的练习</title>
</head>
<body>
    
</body>
<script>
// 定义常量路由（常量路由指的是那些固定的、不会被动态控制的路由）↓
let constantRoute = [
    {
        path: '/login', // 路由路径
        // 使用ES6提供的“import”语法来导入路由组件（即启用路由懒加载（运行时加载））↓
        component: () => import('@/views/login/index.vue'), // 路由组件
        name: 'login', // 为路由命名（路由名称可被用于制作菜单权限）
        // 路由元信息↓
        meta:{
            title:'登录', // 路由标题（在导航菜单上显示）
            icon:'Promotion', // 路由图标（在导航菜单上显示（具体位置是菜单项标题文字的左边），可以使用ElementPlus组件库提供的所有图标组件）
            // 注：选项“hidden”要被写在选项“hidden”的里面（如果写在外面，那么会不生效）
            hidden:true, // 隐藏路由（也就是说该路由的标题在导航菜单上将不会被显示）
        },
        // hidden:true,
        // hidden:false,

    },
    {
        path:'/',
        // component:() => import('@/views/home/index.vue'),
        component:() => import('@/components/layout/index.vue'),
        name:'layout',
        meta:{
            // title:'layout',
            title:'',
            // icon:'Avatar',
            icon:'',
            // hidden:false,
        },
        // hidden:false,
        redirect:'/home', // 重定向（即访问根路径时，自动跳转到home路由）
        children:[
            {
                path:'/home',
                component:() => import('@/views/home/index.vue'),
                name:'home',
                meta: { title: '首页',icon:'HomeFilled',hidden:false },
                // hidden:false,
            },
            /* {
                path:'/test',
                component:() => import('@/views/home/index.vue'),
                name:'home',
                meta: { title: '测试',icon:'Histogram',hidden:false },
                // hidden:false,
            }, */
        ]
    },
    {
        path:'/screen',
        component:() => import('@/views/screen/index.vue'),
        name:'Screen',
        meta:{
            title:'数据大屏',
            icon:'Platform',
            hidden:false,
        },
        // hidden:false,
    },    
    {
        path:'/404',
        component:() => import('@/views/404/index.vue'),
        name:'404',
        meta:{
            title:'404',
            icon:'DocumentDelete',
            hidden:true,
        },
        // hidden:true,
        // hidden:false,
    },    
]
// 定义异步路由（异步路由指的是那些可以被动态控制的路由）↓
let asyncRoute = [
    {
        path:'/acl',
        component:() => import('@/components/layout/index.vue'),
        name:'Acl',
        redirect:'/acl/user', // 重定向（即访问“一级路由”的“根路径”时，自动跳转到它下面的第一个“二级路由”（在此处是“用户管理”））
        meta:{
            title:'权限管理',
            icon:'Lock',
            // hidden:false,
        },
        // 注：当选项“hidden”的值是“false”时，该选项可以被省略（因为不写该选项时其值是“undefined”（未被定义），而“undefined”在做判断时结果就是“false”）↓
        // hidden:false,
        children:[
            {
                path:'/acl/user',
                component:() => import('@/views/acl/user/index.vue'),
                name:'User',
                meta:{ title:'用户管理', icon:'User' },
            },
            {
                path:'/acl/role',
                component:() => import('@/views/acl/role/index.vue'),
                name:'Role',
                // meta:{ title:'角色管理', icon:'UserFilled'}
                meta:{ title:'职位管理', icon:'UserFilled'}
            },
            {
                path:'/acl/permission',
                component:() => import('@/views/acl/permission/index.vue'),
                name:'Permission',
                meta:{ title:'菜单管理', icon:'Monitor'}
            },
        ]
    },
    {
        path:'/product',
        component:() => import('@/components/layout/index.vue'),
        name:'Product',
        redirect: '/product/Trademark', // 重定向（即访问一级路由的“根路径”时，自动跳转到该一级路由下面的第一个二级路由（在此处是“品牌管理”））
        meta:{
            title:'商品管理',
            icon:'Goods',
            // hidden:false,
        },
        // hidden:false,
        children:[
            {
                path:'/product/Trademark',
                component:() => import('@/views/product/trademark/index.vue'),
                name:'Trademark',
                meta:{ title:'品牌管理', icon:'ShoppingCartFull'},
            },
            {
                path:'/product/Attr',
                component:() => import('@/views/product/attr/index.vue'),
                name:'Attr',
                meta:{ title:'属性管理', icon:'ChromeFilled'},
            },
            {
                path:'/product/spu',
                component:() => import('@/views/product/spu/index.vue'),
                name:'Spu',
                meta:{ title:'SPU管理', icon:'Calendar'},
            },
            {
                path:'/product/sku',
                component:() => import('@/views/product/sku/index.vue'),
                name:'Sku',
                meta:{ title:'SKU管理', icon:'Orange'},
            },
        ]
    },
]
// 定义任意路由路径（即捕获除上面三项以外的所有路由路径）↓
let anyRoute = [
    {   
        path:'/:pathMatch(.*)*', // 捕获除上面三项以外的所有路由路径
        redirect:'404',
        name:'Any',
        meta:{title:'任意路由路径',icon:'DataLine',hidden:true},
        // hidden:true,
        // hidden:false,
    },
]
// 用户“刘思齐”已经拥有的菜单权限↓
let menuPermissionOfLiuSiQiHaveHad = ['Product','Trademark','Sku'];
/* function filterAsyncRoute(asyncRoute,menuPermissionOfAUserHaveHad) {
    return asyncRoute.filter((route) => {
        if (menuPermissionOfAUserHaveHad.includes(route.name)) {
            return true;
        }
    })
}
let resultOfThisFilterForLiuSiQi = filterAsyncRoute(asyncRoute,menuPermissionOfLiuSiQiHaveHad)
console.log(resultOfThisFilterForLiuSiQi) // 控制台中显示“Product”下面的4个子路由（即“Trademark”、“Attr”、“spu”和“sku”）全部被筛选出来了。但是由于用户拥有的子路由的菜单权限中只有“Trademark”和“Sku”，所以事情只做到此处是不对的，还需要再进行一次筛选↓ */
function filterAsyncRoute(asyncRoute,menuPermissionOfAUserHaveHad) {
    return asyncRoute.filter((route) => {
        if (menuPermissionOfAUserHaveHad.includes(route.name)) {
            // 关键代码↓
            if (route.children&&route.children.length>0) {
                // 在某个路由有且至少有一个子路由时递归调用此函数，对子路由进行筛选，并把筛选结果作为当前路由的子路由（注：此处必须赋值，否则筛选结果将没有作用）↓
                route.children = filterAsyncRoute(route.children,menuPermissionOfAUserHaveHad)
            }
            return true;
        }
    })
}
// 注：由于数组的“filter”方法会返回一个满足条件的新数组，所以此处需要使用变量来接收该方法返回的新数组↓
let resultOfThisFilterForLiuSiQi = filterAsyncRoute(asyncRoute,menuPermissionOfLiuSiQiHaveHad)
console.log(resultOfThisFilterForLiuSiQi) // Array(1)
console.log([...constantRoute,resultOfThisFilterForLiuSiQi,anyRoute]) // 控制台中将显示刘思齐能访问的所有路由
console.log(asyncRoute) // Array(2)（由于语句“route.children = filterAsyncRoute(route.children,menuPermissionOfAUserHaveHad)”对满足条件的一级路由的子路由进行了重新赋值），所以此时异步路由将不再是原来的数组了，而是变成了筛选后的新数组。这样做后因为会修改后续其他用户登录时异步路由的原始数据，所以此处不能这样做。这种情况下需要使用“深拷贝（用lodash来做）”来保留“异步路由的原始数据”
</script>
</html>